<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Buffer-Oriented Parsing</title>
<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;Boost.Beast">
<link rel="up" href="../using_http.html" title="Using HTTP">
<link rel="prev" href="buffer_oriented_serializing.html" title="Buffer-Oriented Serializing">
<link rel="next" href="chunked_encoding.html" title="Chunked Encoding">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="buffer_oriented_serializing.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_http.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="chunked_encoding.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="beast.using_http.buffer_oriented_parsing"></a><a class="link" href="buffer_oriented_parsing.html" title="Buffer-Oriented Parsing">Buffer-Oriented
      Parsing</a>
</h3></div></div></div>
<p>
        A subclass of <a class="link" href="../ref/boost__beast__http__basic_parser.html" title="http::basic_parser"><code class="computeroutput"><span class="identifier">basic_parser</span></code></a> can be invoked directly,
        without using the provided stream operations. This could be useful for implementing
        algorithms on objects whose interface does not conform to <a class="link" href="../concepts/streams.html" title="Streams"><span class="bold"><strong>Stream</strong></span></a>. For example, a <a href="http://zeromq.org/" target="_top"><span class="bold"><strong>ZeroMQ</strong></span> socket</a>. The basic parser interface
        is interactive; the caller invokes the function <a class="link" href="../ref/boost__beast__http__basic_parser/put.html" title="http::basic_parser::put"><code class="computeroutput"><span class="identifier">basic_parser</span><span class="special">::</span><span class="identifier">put</span></code></a> repeatedly with buffers until
        an error occurs or the parsing is done. The function <a class="link" href="../ref/boost__beast__http__basic_parser/put_eof.html" title="http::basic_parser::put_eof"><code class="computeroutput"><span class="identifier">basic_parser</span><span class="special">::</span><span class="identifier">put_eof</span></code></a> Is used when the caller
        knows that there will never be more data (for example, if the underlying
        connection is closed),
      </p>
<h5>
<a name="beast.using_http.buffer_oriented_parsing.h0"></a>
        <span class="phrase"><a name="beast.using_http.buffer_oriented_parsing.parser_options"></a></span><a class="link" href="buffer_oriented_parsing.html#beast.using_http.buffer_oriented_parsing.parser_options">Parser
        Options</a>
      </h5>
<p>
        The parser provides a few options which may be set before parsing begins:
      </p>
<div class="table">
<a name="beast.using_http.buffer_oriented_parsing.parser_options0"></a><p class="title"><b>Table&#160;1.19.&#160;Parser Options</b></p>
<div class="table-contents"><table class="table" summary="Parser Options">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
                <p>
                  Name
                </p>
              </th>
<th>
                <p>
                  Default
                </p>
              </th>
<th>
                <p>
                  Description
                </p>
              </th>
</tr></thead>
<tbody>
<tr>
<td>
                <p>
                  <a class="link" href="../ref/boost__beast__http__basic_parser/eager/overload2.html" title="http::basic_parser::eager (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">eager</span></code></a>
                </p>
              </td>
<td>
                <p>
                  <code class="computeroutput"><span class="keyword">false</span></code>
                </p>
              </td>
<td>
                <p>
                  Normally the parser returns after successfully parsing a structured
                  element (header, chunk header, or chunk body) even if there are
                  octets remaining in the input. This is necessary when attempting
                  to parse the header first, or when the caller wants to inspect
                  information which may be invalidated by subsequent parsing, such
                  as a chunk extension. The <code class="computeroutput"><span class="identifier">eager</span></code>
                  option controls whether the parser keeps going after parsing structured
                  element if there are octets remaining in the buffer and no error
                  occurs. This option is automatically set or cleared during certain
                  stream operations to improve performance with no change in functionality.
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  <a class="link" href="../ref/boost__beast__http__basic_parser/skip/overload2.html" title="http::basic_parser::skip (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">skip</span></code></a>
                </p>
              </td>
<td>
                <p>
                  <code class="computeroutput"><span class="keyword">false</span></code>
                </p>
              </td>
<td>
                <p>
                  This option controls whether or not the parser expects to see an
                  HTTP body, regardless of the presence or absence of certain fields
                  such as Content-Length or a chunked Transfer-Encoding. Depending
                  on the request, some responses do not carry a body. For example,
                  a 200 response to a <a href="https://tools.ietf.org/html/rfc7231#section-4.3.6" target="_top">CONNECT</a>
                  request from a tunneling proxy, or a response to a <a href="https://tools.ietf.org/html/rfc7231#section-4.3.2" target="_top">HEAD</a>
                  request. In these cases, callers may use this function inform the
                  parser that no body is expected. The parser will consider the message
                  complete after the header has been received.
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  <a class="link" href="../ref/boost__beast__http__basic_parser/body_limit.html" title="http::basic_parser::body_limit"><code class="computeroutput"><span class="identifier">body_limit</span></code></a>
                </p>
              </td>
<td>
                <p>
                  1MB/8MB
                </p>
              </td>
<td>
                <p>
                  This function sets the maximum allowed size of the content body.
                  When a body larger than the specified size is detected, an error
                  is generated and parsing terminates. This setting helps protect
                  servers from resource exhaustion attacks. The default limit when
                  parsing requests is 1MB, and for parsing responses 8MB.
                </p>
              </td>
</tr>
<tr>
<td>
                <p>
                  <a class="link" href="../ref/boost__beast__http__basic_parser/header_limit.html" title="http::basic_parser::header_limit"><code class="computeroutput"><span class="identifier">header_limit</span></code></a>
                </p>
              </td>
<td>
                <p>
                  8KB
                </p>
              </td>
<td>
                <p>
                  This function sets the maximum allowed size of the header including
                  all field name, value, and delimiter characters and also including
                  the CRLF sequences in the serialized input.
                </p>
              </td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="beast.using_http.buffer_oriented_parsing.read_from_std_istream"></a><a class="link" href="buffer_oriented_parsing.html#beast.using_http.buffer_oriented_parsing.read_from_std_istream" title="Read From std::istream">Read
        From std::istream</a>
</h4></div></div></div>
<p>
          The standard library provides the type <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code>
          for performing high level read operations on character streams. The variable
          <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span></code> is based on this input stream. This
          example uses the buffer oriented interface of <a class="link" href="../ref/boost__beast__http__basic_parser.html" title="http::basic_parser"><code class="computeroutput"><span class="identifier">basic_parser</span></code></a> to build a stream
          operation which parses an HTTP message from a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code>:
        </p>
<pre class="programlisting"><span class="comment">/** Read a message from a `std::istream`.

    This function attempts to parse a complete HTTP/1 message from the stream.

    @param is The `std::istream` to read from.

    @param buffer The buffer to use.

    @param msg The message to store the result.

    @param ec Set to the error, if any occurred.
*/</span>
<span class="keyword">template</span><span class="special">&lt;</span>
    <span class="keyword">class</span> <span class="identifier">Allocator</span><span class="special">,</span>
    <span class="keyword">bool</span> <span class="identifier">isRequest</span><span class="special">,</span>
    <span class="keyword">class</span> <span class="identifier">Body</span><span class="special">&gt;</span>
<span class="keyword">void</span>
<span class="identifier">read_istream</span><span class="special">(</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;</span> <span class="identifier">is</span><span class="special">,</span>
    <span class="identifier">basic_flat_buffer</span><span class="special">&lt;</span><span class="identifier">Allocator</span><span class="special">&gt;&amp;</span> <span class="identifier">buffer</span><span class="special">,</span>
    <span class="identifier">message</span><span class="special">&lt;</span><span class="identifier">isRequest</span><span class="special">,</span> <span class="identifier">Body</span><span class="special">,</span> <span class="identifier">fields</span><span class="special">&gt;&amp;</span> <span class="identifier">msg</span><span class="special">,</span>
    <span class="identifier">error_code</span><span class="special">&amp;</span> <span class="identifier">ec</span><span class="special">)</span>
<span class="special">{</span>
    <span class="comment">// Create the message parser</span>
    <span class="comment">//</span>
    <span class="comment">// Arguments passed to the parser's constructor are</span>
    <span class="comment">// forwarded to the message constructor. Here, we use</span>
    <span class="comment">// a move construction in case the caller has constructed</span>
    <span class="comment">// their message in a non-default way.</span>
    <span class="comment">//</span>
    <span class="identifier">parser</span><span class="special">&lt;</span><span class="identifier">isRequest</span><span class="special">,</span> <span class="identifier">Body</span><span class="special">&gt;</span> <span class="identifier">p</span><span class="special">{</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)};</span>

    <span class="keyword">do</span>
    <span class="special">{</span>
        <span class="comment">// Extract whatever characters are presently available in the istream</span>
        <span class="keyword">if</span><span class="special">(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">rdbuf</span><span class="special">()-&gt;</span><span class="identifier">in_avail</span><span class="special">()</span> <span class="special">&gt;</span> <span class="number">0</span><span class="special">)</span>
        <span class="special">{</span>
            <span class="comment">// Get a mutable buffer sequence for writing</span>
            <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">prepare</span><span class="special">(</span>
                <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">&gt;(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">rdbuf</span><span class="special">()-&gt;</span><span class="identifier">in_avail</span><span class="special">()));</span>

            <span class="comment">// Now get everything we can from the istream</span>
            <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">commit</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">&gt;(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">readsome</span><span class="special">(</span>
                <span class="keyword">reinterpret_cast</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">*&gt;(</span><span class="identifier">b</span><span class="special">.</span><span class="identifier">data</span><span class="special">()),</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">size</span><span class="special">())));</span>
        <span class="special">}</span>
        <span class="keyword">else</span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span>
        <span class="special">{</span>
            <span class="comment">// Our buffer is empty and we need more characters, </span>
            <span class="comment">// see if we've reached the end of file on the istream</span>
            <span class="keyword">if</span><span class="special">(!</span> <span class="identifier">is</span><span class="special">.</span><span class="identifier">eof</span><span class="special">())</span>
            <span class="special">{</span>
                <span class="comment">// Get a mutable buffer sequence for writing</span>
                <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">prepare</span><span class="special">(</span><span class="number">1024</span><span class="special">);</span>

                <span class="comment">// Try to get more from the istream. This might block.</span>
                <span class="identifier">is</span><span class="special">.</span><span class="identifier">read</span><span class="special">(</span><span class="keyword">reinterpret_cast</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">*&gt;(</span><span class="identifier">b</span><span class="special">.</span><span class="identifier">data</span><span class="special">()),</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">size</span><span class="special">());</span>

                <span class="comment">// If an error occurs on the istream then return it to the caller.</span>
                <span class="keyword">if</span><span class="special">(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">fail</span><span class="special">()</span> <span class="special">&amp;&amp;</span> <span class="special">!</span> <span class="identifier">is</span><span class="special">.</span><span class="identifier">eof</span><span class="special">())</span>
                <span class="special">{</span>
                    <span class="comment">// We'll just re-use io_error since std::istream has no error_code interface.</span>
                    <span class="identifier">ec</span> <span class="special">=</span> <span class="identifier">make_error_code</span><span class="special">(</span><span class="identifier">errc</span><span class="special">::</span><span class="identifier">io_error</span><span class="special">);</span>
                    <span class="keyword">return</span><span class="special">;</span>
                <span class="special">}</span>

                <span class="comment">// Commit the characters we got to the buffer.</span>
                <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">commit</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">&gt;(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">gcount</span><span class="special">()));</span>
            <span class="special">}</span>
            <span class="keyword">else</span>
            <span class="special">{</span>
                <span class="comment">// Inform the parser that we've reached the end of the istream.</span>
                <span class="identifier">p</span><span class="special">.</span><span class="identifier">put_eof</span><span class="special">(</span><span class="identifier">ec</span><span class="special">);</span>
                <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
                    <span class="keyword">return</span><span class="special">;</span>
                <span class="keyword">break</span><span class="special">;</span>
            <span class="special">}</span>
        <span class="special">}</span>

        <span class="comment">// Write the data to the parser</span>
        <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">bytes_used</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">put</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">data</span><span class="special">(),</span> <span class="identifier">ec</span><span class="special">);</span>

        <span class="comment">// This error means that the parser needs additional octets.</span>
        <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span> <span class="special">==</span> <span class="identifier">error</span><span class="special">::</span><span class="identifier">need_more</span><span class="special">)</span>
            <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span>
        <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span>
            <span class="keyword">return</span><span class="special">;</span>

        <span class="comment">// Consume the buffer octets that were actually parsed.</span>
        <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">consume</span><span class="special">(</span><span class="identifier">bytes_used</span><span class="special">);</span>
    <span class="special">}</span>
    <span class="keyword">while</span><span class="special">(!</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">is_done</span><span class="special">());</span>

    <span class="comment">// Transfer ownership of the message container in the parser to the caller.</span>
    <span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">release</span><span class="special">();</span>
<span class="special">}</span>
</pre>
<div class="tip"><table border="0" summary="Tip">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td>
<th align="left">Tip</th>
</tr>
<tr><td align="left" valign="top"><p>
            Parsing from a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code> could be implemented using
            an alternate strategy: adapt the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code>
            interface to a <a href="../../../../../../doc/html/boost_asio/reference/SyncReadStream.html" target="_top"><span class="bold"><strong>SyncReadStream</strong></span></a>, enabling use with the
            library's existing stream algorithms. This is left as an exercise for
            the reader.
          </p></td></tr>
</table></div>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2016, 2017 Vinnie Falco<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="buffer_oriented_serializing.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_http.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="chunked_encoding.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
